#include "Thread.h"
#include "Mutex.h"
#include "common.h"
#include <time.h>
#include <sys/syscall.h>
#include <linux/unistd.h>

static void* ProcessProc(void* lParam)
{
    Thread* pthis = (Thread*)lParam;
    if(!pthis)
    {
        return 0;
    }
    pthis->Process();
    return 0;
}

Thread::Thread()
    : m_thread(0)
{
    //ctor
    m_bRun = false;
}

Thread::~Thread()
{
    //dtor
    StopThread();
}

int Thread::StartThread(void)
{
    if(!m_bRun)
    {
        m_bRun = true;
        int errcode = pthread_create(&m_thread,0,ProcessProc,this);
        if(errcode)
        {
            m_bRun = false;
            perror("pthread_create");
        }

        return errcode;
    }
    return 0;
}

void Thread::StopThread(void)
{
    m_bRun = false;
    if(m_thread)
    {
        void* retVal;
        pthread_join(m_thread,&retVal);
        m_thread = 0;
    }
}

namespace CurrentThread
{
  __thread int t_cachedTid = 0;
  __thread char t_tidString[32];
  __thread int t_tidStringLength = 6;
  __thread const char* t_threadName = "unknown";
}

namespace detail
{
    pid_t gettid()
    {
      return static_cast<pid_t>(::syscall(SYS_gettid));
    }
}

void CurrentThread::CacheTid()
{
    if (t_cachedTid == 0)
    {
        t_cachedTid = detail::gettid();
        t_tidStringLength = snprintf(t_tidString, sizeof t_tidString, "%5d ", t_cachedTid);
    }
}

bool CurrentThread::IsMainThread()
{
    return Tid() == ::getpid();
}

static const int kMicroSecondsPerSecond = 1000 * 1000;

void CurrentThread::SleepUsec(int64_t usec)
{
    struct timespec ts = { 0, 0 };
    ts.tv_sec = static_cast<time_t>(usec / kMicroSecondsPerSecond);
    ts.tv_nsec = static_cast<long>(usec % kMicroSecondsPerSecond * 1000);
    ::nanosleep(&ts, NULL);
}
